<?php

/**
 * @class coupon
 * @brief 优惠券模块
 */
class Coupon
{
    public $error;

    public function __construct()
    {
        $this->logObj = new Log();

    }

    /**
     * 给用户发送优惠券
     *
     * @param        $coupon_group_id   优惠券主id
     * @param        $send_type         优惠发放类型
     * @param        $user_id           用户id
     * @param int    $num
     * @param        string             优惠券当前商品售卖的时候 自动发货领取的订单号
     *
     * @return bool
     */
    public function setCouponToUser($coupon_group_id, $send_type, $user_id, $num = 1, $receive_order_no = '')
    {
        if (empty($coupon_group_id) || empty($user_id) || empty($send_type)) {
            $this->error = "用户领取优惠券出错了：参数不完整！coupon_group_id:{$coupon_group_id},user_id:{$user_id},send_type:{$send_type}";

            return false;
        }
        //获取优惠券主要信息
        $this->getCouponGroupsInfo($coupon_group_id);
        if ($this->error) {
            $this->error;

            return false;
        }
        //随机获取一张可以使用的优惠券
        $couponInfo = $this->getRandomNoUseCoupon($coupon_group_id, $send_type, $num);
        if ($this->error) {
            $this->error;

            return false;
        }
        if (empty($couponInfo)) {
            $this->error = "用户领取优惠券出错了：优惠券已经被领取完了！";

            return false;
        }
        //给用户发送优惠券 保存到用户优惠券表
        foreach ($couponInfo as $value) {
            $this->setCouponToUserDb($coupon_group_id, $value['id'], $value['code'], $user_id, $receive_order_no);
            if ($this->error) {
                $this->error;

                return false;
            }
        }

        return true;
    }


    /**
     * 获取优惠券信息
     *
     * @param $coupon_group_id
     *
     * @return array|bool
     */
    public function getCouponGroupsInfo($coupon_group_id)
    {
        if (empty($coupon_group_id)) {
            $this->error = "获取优惠券信息出错了：参数不完整！coupon_group_id:{$coupon_group_id}";

            return false;
        }
        $couponGroupsDb   = new IModel('coupon_groups');
        $nowDate          = ITime::getDateTime();
        $where            = "id=$coupon_group_id and status = 1 ";
        $couponGroupsInfo = $couponGroupsDb->getObj($where);
        if (empty($couponGroupsInfo) || $couponGroupsInfo['end_time'] < $nowDate) {
            $this->error = "优惠券已经过期！";

            return false;
        }

        return $couponGroupsInfo;

    }

    /**
     * 随机获取优惠券
     *
     * @param     $coupon_group_id
     * @param     $send_type
     * @param int $num
     *
     * @return array|bool
     */
    public function getRandomNoUseCoupon($coupon_group_id, $send_type, $num = 1)
    {
        if (empty($coupon_group_id) || empty($send_type)) {
            $this->error = "随机获取一张优惠券码出错了：参数不完整！coupon_group_id:{$coupon_group_id},send_type:{$send_type}";

            return false;
        }

        $couponInfo = array();
        //加入到道具的优惠是没有生成，是要领取道具的在生成写入到优惠券表
        if ($send_type == 2) {
            $couponAddDB = new IModel('coupon');
            for ($i = 0; $i < $num; $i++) {
                $couponData = array(
                    'coupon_group_id' => $coupon_group_id,
                    'send_type'       => $send_type,
                    'create_time'     => ITime::getDateTime(),
                    'status'          => 1,
                    'code'            => $this->getUniqueCode(16)
                );
                $couponAddDB->setData($couponData);
                $couponId         = $couponAddDB->add();
                $couponData['id'] = $couponId;
                $couponInfo[]     = $couponData;
            }
        } else {
            $couponDB        = new IQuery('coupon');
            $couponDB->where = "coupon_group_id=$coupon_group_id and status=1 and send_type=$send_type";
            $couponDB->order = 'rand()';
            $couponDB->limit = $num;
            $couponInfo      = $couponDB->find();
        }

        return $couponInfo;
    }


    /**
     * 给用户发送一张优惠券
     *
     * @param $coupon_group_id
     * @param $coupon_id
     * @param $coupon_code
     * @param $user_id
     * @param $receive_order_no
     *
     * @return bool|int
     */
    public function setCouponToUserDb($coupon_group_id, $coupon_id, $coupon_code, $user_id, $receive_order_no)
    {
        if (empty($coupon_group_id) || empty($user_id) || empty($coupon_code)) {
            $this->error = "给用户发送优惠失败：参数不完整！coupon_group_id:{$coupon_group_id},user_id:{$user_id},coupon_code:{$coupon_code}";

            return false;
        }
        $CouponUserDb   = new IModel('coupon_user');
        $CouponUserData = array(
            'coupon_group_id'  => $coupon_group_id,
            'coupon_id'        => $coupon_id,
            'coupon_code'      => $coupon_code,
            'user_id'          => $user_id,
            'redeem_time'      => ITime::getDateTime(),
            'receive_order_no' => $receive_order_no,
        );

        $CouponUserDb->setData($CouponUserData);
        $CouponUserId = $CouponUserDb->add();
        if ($CouponUserId) {
            $couponDb           = new IModel('coupon');
            $ruleData['status'] = 2;
            $couponDb->setData($ruleData);
            $where = "coupon_group_id=$coupon_group_id and code='" . $coupon_code . "'";
            $couponDb->update($where);
        }

        return $CouponUserId;

    }

    /**
     * 生成优惠券uuid
     *
     * @param $length   int 长度
     *
     * @return string   uuid
     */
    public function getUniqueCode($length)
    {
        //前两位数为日期的递增值，用于去重，同时首位必须为字母
        //取得当前天与20150823的差值，并且取26*36作为求余值
        $subDay    = floor(time() / 86400 - 16670);
        $day       = $subDay % 936;
        $dayFirst  = floor($day / 36);
        $daySecond = $day % 36;
        $dayFirst  = chr($dayFirst + 97);
        $daySecond = $daySecond >= 10 ? chr($daySecond + 87) : $daySecond;

        $randomNum = $dayFirst . $daySecond;

        $str = '1234567890abcdefghijklmnopqrstuvwxyz';
        $len = strlen($str) - 1;
        for ($i = 0; $i < $length - 2; $i++) {
            $num       = rand(0, $len);
            $key       = $str[$num];
            $randomNum = $randomNum . $key;
        }

        return $randomNum;
    }


    /**
     * 获取用户的优惠券
     *
     * @param $user_id
     * @param $is_used       0未使用,1已使用
     * @param $coupon_status 0禁用,1可用,2已被领取,3已被使用,4已过期
     *
     * @return array
     */
    public function getUserCoupon($user_id, $is_used = '', $coupon_status = '')
    {
        if (empty($user_id)) {
            return array();
        }

        $couponUserDb = new IModel('coupon_user as cu,coupon as c,goods_coupon as gc');
        $where        = "cu.user_id=$user_id and cu.coupon_group_id=c.coupon_group_id and cu.coupon_id=c.id and cu.coupon_group_id=gc.coupon_group_id";
        if ($is_used !== '') {
            if ($is_used == 0) {
                $where .= " and cu.is_used=$is_used and c.status=2";
            } else {
                $where .= " and cu.is_used=$is_used";
            }
        }
        if (!empty($coupon_status)) {
            if (is_array($coupon_status)) {
                $couponStatus = join(",", $coupon_status);
                $where        .= " and c.status in($couponStatus)";
            } else {
                $where .= " and c.status=$coupon_status";
            }
        }
        $filed        = "cu.coupon_group_id,cu.coupon_id,cu.coupon_code,cu.is_used,c.status,gc.goods_id";
        $order        = "cu.redeem_time desc";
        $limit        = 500;
        $couponResult = $couponUserDb->query($where, $filed, $order, $limit);
        if (empty($couponResult)) {
            return array();
        }
        //获取优惠券主要信息
        $couponGroupArr = array();
        foreach ($couponResult as $value) {
            $couponGroupArr[] = $value['coupon_group_id'];
        }
        $couponGroupStr    = join(',', array_unique($couponGroupArr));
        $couponGroupDb     = new IModel('coupon_groups');
        $couponGroupResult = $couponGroupDb->query("id in(" . $couponGroupStr . ")", "*,date_format(start_time,'%Y-%m-%d') as start_time, date_format(end_time,'%Y-%m-%d') as end_time");
        if (empty($couponGroupResult)) {
            return array();
        }
        $couponGroupInfo = array();
        foreach ($couponGroupResult as $c_value) {
            $couponGroupInfo[$c_value['id']] = $c_value;
        }
        //拼接优惠券信息数据
        $couponInfoData = array();
        foreach ($couponResult as $value) {
            $value['coupon_detail_info'] = $couponGroupInfo[$value['coupon_group_id']];
            $couponInfoData []           = $value;
        }

        return $couponInfoData;
    }


    /**
     * 用户使用优惠券
     *
     * @param        $user_id
     * @param        $coupon_code
     * @param        $order_no
     * @param string $remark
     *
     * @return bool
     */
    public function useOfCoupon($user_id, $coupon_code, $order_no, $remark = '')
    {
        if (empty($user_id) || empty($coupon_code) || empty($order_no)) {
            $this->error = "用户使用优惠券出错啦：参数不完整！user_id:{$user_id},coupon_code:{$coupon_code},order_no:{$order_no}";

            return false;
        }
        //读取优惠信息 判断是否被使用
        $couponUserAndCouponDb = new IModel('coupon_user as cu,coupon as c');
        $nowDate               = ITime::getDateTime();
        $where                 = "cu.user_id=$user_id and cu.is_used = 0 and cu.coupon_code='$coupon_code' and c.coupon_group_id=cu.coupon_group_id and c.status=2";
        $couponUserInfo        = $couponUserAndCouponDb->getObj($where, 'cu.coupon_group_id,cu.coupon_id,cu.coupon_code,c.status,cu.is_used');
        if (empty($couponUserInfo)) {
            $this->error = "用户使用优惠券出错啦：领取的优惠券异常！";

            return false;
        }
        //读取优惠券主信息 判断优惠是否过期，如果过期 则直接设置过期
        $couponGroupsInfo = $this->getCouponGroupsInfo($couponUserInfo['coupon_group_id']);
        $couponDb         = new IModel('coupon');
        if ($this->error) {
            $this->error;
            $couponDb->setData(array(
                'status'      => 4,
                'update_time' => $nowDate
            ));
            $couponWhere = "code='$coupon_code'";
            $couponDb->update($couponWhere);

            return false;
        }
        //更新用户优惠券表
        $couponUserDb = new IModel('coupon_user');
        $couponUserDb->setData(array(
            'is_used'  => 1,
            'order_no' => $order_no,
            'use_time' => $nowDate,
            'remark'   => $remark
        ));
        $couponUserWhere = "coupon_code='$coupon_code'";
        $couponUserRes   = $couponUserDb->update($couponUserWhere);
        //更新优惠券表
        $couponDb->setData(array(
            'status'      => 3,
            'update_time' => $nowDate
        ));
        $couponWhere = "code='$coupon_code'";
        $couponRes   = $couponDb->update($couponWhere);

        if ($couponUserRes === false || $couponRes === false) {
            $this->error = "用户使用优惠券出错啦：更新优惠券状态错误！";

            return false;
        }
        $propsParam = array(
            'user_id'  => $user_id,
            'props_id' => $couponGroupsInfo['props_id'],
            'quantity' => 1,
            'from_id'  => $order_no,
        );
        $userRes    = $this->syncUsePropCoupon($propsParam);
        if ($userRes === false) {
            $this->error = "用户使用优惠券出错啦：同步使用道具出错了！";

            return false;
        }

        return true;
    }

    /**
     * 使用优惠券的时候有加入道具的 要同步核销它
     *
     * @param $propsParam
     *
     * @return bool
     */
    public function syncUsePropCoupon($propsParam)
    {
        if (empty($propsParam['props_id'])) {
            return true;
        }
        $zxlObj = new  zxlhelper();
        $result = $zxlObj->syncUsePropCoupon($propsParam);

        return $result;
    }

    /**
     * 获取购车里商品是否有可以使用的优惠券
     *
     * @param $goods_list
     * @param $user_id
     *
     * @return array|bool
     */
    public function getCartCanUseCoupon($goods_list, $user_id)
    {
        if (empty($goods_list) || empty($user_id)) {
            return array();
        }
        //组合商品信息
        $goodIds  = array();
        $goodInfo = array();
        foreach ($goods_list as $value) {
            $goodIds[]                    = $value['goods_id'];
            $goodInfo[$value['goods_id']] = $value;
        }
        //判断购物车里的商品有哪些优惠券可以使用
        $goodsCouponDb  = new IModel('goods_coupon');
        $goodIdStr      = join(',', $goodIds);
        $goodsCouponRes = $goodsCouponDb->query("goods_id in(" . $goodIdStr . ")", 'coupon_group_id,goods_id');
        //组合购买的商品里设置了哪些优惠可以使用 组合设置优惠券后的商品信息
        $couponGroupIds  = array();
        $couponGoodsInfo = array();
        if ($goodsCouponRes) {
            foreach ($goodsCouponRes as $value) {
                $couponGoodsInfo[$value['coupon_group_id']] = $goodInfo[$value['goods_id']];
                $couponGroupIds[]                           = $value['coupon_group_id'];
            }
        }
        //先获取出用户所有可以使用的优惠券 如果用户没有领取到优惠券直接返回空
        $couponUserDb     = new IModel('coupon_user as cu,coupon as c');
        $couponUseWhere   = "cu.user_id=$user_id and cu.coupon_group_id=c.coupon_group_id and cu.coupon_id=c.id and cu.is_used=0 and c.status=2";
        $filed            = "cu.coupon_group_id,cu.coupon_id,cu.coupon_code,cu.is_used,c.status";
        $order            = "redeem_time desc";
        $couponUserResult = $couponUserDb->query($couponUseWhere, $filed, $order);
        if (empty($couponUserResult)) {
            return array();
        }
        //进行筛选下 用户领取的优惠券哪些是购车里的商品 可以使用的优惠券
        $userCanUseCouponIds    = array();
        $userCanNotUseCouponIds = array();
        $userCouponAllIds       = array();
        foreach ($couponUserResult as $cu_value) {
            if (in_array($cu_value['coupon_group_id'], $couponGroupIds)) {
                $userCanUseCouponIds[] = $cu_value['coupon_id'];
            } else {
                $userCanNotUseCouponIds[] = $cu_value['coupon_id'];
            }
            $userCouponAllIds[] = $cu_value['coupon_id'];
        }
        $couponGroupIdStr = join(',', $userCouponAllIds);
        //获取下优惠状态已经是否过期正常
        $couponDb          = new IQuery('coupon as c');
        $couponDb->join    = "left join coupon_groups as cg  on cg.id = c.coupon_group_id";
        $couponDb->where   = "c.id in($couponGroupIdStr) and c.status = 2 and cg.status=1";
        $couponDb->fields  = "cg.*,c.code,c.id as coupon_id,date_format(cg.start_time,'%Y-%m-%d') as start, date_format(cg.end_time,'%Y-%m-%d') as end";
        $couponGroupsQuery = $couponDb->find();
        //如果优惠券被删除了，没有查询到就返回空
        if (empty($couponGroupsQuery)) {
            return array();
        }
        //组合下数据优惠券信息
        $couponGroupsRes = array();
        foreach ($couponGroupsQuery as $value) {
            $couponGroupsRes[$value['coupon_id']] = $value;
        }
        $nowDate = ITime::getTime();
        //筛选下可使用的优惠券是否过期 是否开始了 不然就排除加入的不可使用的优惠券 判断商品购买的商品是否符合优惠使用条件
        //组合下可使用的优惠券数据
        $endCanUseCoupon    = array();
        $endCanNotUseCoupon = array();
        if ($userCanUseCouponIds) {
            foreach ($userCanUseCouponIds as $value) {
                //判断是否开始了
                if (strtotime($couponGroupsRes[$value]['start_time']) > $nowDate) {
                    array_push($userCanNotUseCouponIds, $value);
                    continue;
                }
                //判断是否结束过期了
                if (strtotime($couponGroupsRes[$value]['end_time']) < $nowDate) {
                    array_push($userCanNotUseCouponIds, $value);
                    continue;
                }
                //判断是否满足使用条件
                if ($couponGroupsRes[$value]['condition'] == 2) {
                    $joinCouponGood = $couponGoodsInfo[$couponGroupsRes[$value]['id']];
                    if ($joinCouponGood) {
                        $full_money = $couponGroupsRes[$value]['full_money'];
                        $full_point = $couponGroupsRes[$value]['full_point'];
                        if ($full_money && $joinCouponGood['pay_price_sum'] < $full_money) {
                            array_push($userCanNotUseCouponIds, $value);
                            $couponGroupsRes[$value]['unable_use_reason'] = "未满足使用条件";
                            continue;
                        }
                        if ($full_point && $joinCouponGood['pay_point_sum'] < $full_point) {
                            array_push($userCanNotUseCouponIds, $value);
                            $couponGroupsRes[$value]['unable_use_reason'] = "未满足使用条件";
                            continue;
                        }
                    }
                }
                $endCanUseCoupon[] = $couponGroupsRes[$value];
            }

        }
        if ($userCanNotUseCouponIds) {
            //组合不可使用的优惠券的数据
            foreach ($userCanNotUseCouponIds as $value) {
                if (strtotime($couponGroupsRes[$value]['start_time']) > $nowDate) {
                    $couponGroupsRes[$value]['unable_use_reason'] = "未到使用日期";
                }
                if (strtotime($couponGroupsRes[$value]['end_time']) < $nowDate) {
                    $couponGroupsRes[$value]['unable_use_reason'] = "优惠券已经过期";
                }
                if (!isset($couponGroupsRes[$value]['unable_use_reason'])) {
                    $couponGroupsRes[$value]['unable_use_reason'] = "所结算商品中没有符合条件的商品";
                }
                $endCanNotUseCoupon[] = $couponGroupsRes[$value];
            }
        }
        $data['can_use_coupon']     = $endCanUseCoupon;
        $data['can_not_use_coupon'] = $endCanNotUseCoupon;

        return $data;
    }

    /**
     * 优惠使用校验以及使用优惠券后金额积分结算
     *
     * @param $buyGoodsList
     * @param $couponCodeArr
     *
     * @return array|bool
     */
    public function useCouponCheckAndBalance($buyGoodsList, $couponCodeArr)
    {
        if (empty($buyGoodsList)) {
            $this->error['code'] = "error";
            $this->error['msg']  = "没有购买商品信息";

            return false;
        }
        if (empty($couponCodeArr)) {
            $this->error['code'] = "no_use";
            $this->error['msg']  = "没有使用优惠券";

            return $buyGoodsList;
        }
        $couponCodeStr = join("','", $couponCodeArr);
        //获取下优惠状态已经是否过期正常
        $couponDb         = new IQuery('coupon as c');
        $couponDb->join   = "left join coupon_groups as cg  on cg.id = c.coupon_group_id left join goods_coupon  as gc on gc.coupon_group_id=c.coupon_group_id ";
        $couponDb->where  = "c.code in('$couponCodeStr') and c.status = 2 and cg.status=1";
        $couponDb->fields = "cg.*,c.code,c.id as coupon_id,gc.goods_id";
        $couponQuery      = $couponDb->find();
        if (empty($couponQuery)) {
            $this->error['code'] = "error";
            $this->error['msg']  = "优惠券异常，没有查询到您的优惠券";

            return false;
        }
        //判断优惠券是否开始了 是否过期 一个商品只能使用限定的一张优惠券
        $nowDate      = ITime::getTime();
        $canUseCoupon = array();
        foreach ($couponQuery as $value) {
            if (strtotime($value['start_time']) > $nowDate) {
                $this->error['code'] = "error";
                $this->error['msg']  = "您使用的优惠券:" . $value['code'] . "异常了，还没到开始时间";

                return false;
            }
            //判断是否结束过期了
            if (strtotime($value['end_time']) < $nowDate) {
                $this->error['code'] = "error";
                $this->error['msg']  = "您使用的优惠券:" . $value['code'] . "异常了，已经过期了";

                return false;
            }
            if (array_key_exists($value['goods_id'], $canUseCoupon)) {
                $this->error['code'] = "error";
                $this->error['msg']  = "同一个商品，一个订单只可使用一张优惠券";

                return false;
            } else {
                $canUseCoupon[$value['goods_id']] = $value;
            }
        }
        $discount              = array();
        $use_coupon_code       = '';
        $goods_use_coupon_info = array();
        //判断购买的商品是否满足使用的条件 是否满积分 满金额
        foreach ($buyGoodsList['goodsList'] as &$value) {
            if ($canUseCoupon[$value['goods_id']]['condition'] == 2) {
                $full_money = $canUseCoupon[$value['goods_id']]['full_money'];
                $full_point = $canUseCoupon[$value['goods_id']]['full_point'];
                if ($full_money && $value['pay_price_sum'] < $full_money) {
                    $this->error['code'] = "error";
                    $this->error['msg']  = "您使用的优惠券:" . $canUseCoupon[$value['goods_id']]['code'] . " 未满足使用条件：" . " 满{$full_money}元可用";

                    return false;
                }
                if ($full_point && $value['pay_point_sum'] < $full_point) {
                    $this->error['code'] = "error";
                    $this->error['msg']  = "您使用的优惠券:" . $canUseCoupon[$value['goods_id']]['code'] . " 未满足使用条件：" . " 满{$full_point}积分可用";

                    return false;
                }
            }

            $discount_point                 = $canUseCoupon[$value['goods_id']]['discount_point'];
            $discount_money                 = $canUseCoupon[$value['goods_id']]['discount_money'];
            $value['discount_point']        += $discount_point;
            $value['discount_price']        += $discount_money;
            $discount['discount_point_sum'] += $discount_point;
            $discount['discount_price_sum'] += $discount_money;
            $value['use_coupon_code']       = $canUseCoupon[$value['goods_id']]['code'] ? $canUseCoupon[$value['goods_id']]['code'] : '';
            if ($value['use_coupon_code']) {
                $use_coupon_code .= $value['use_coupon_code'] . ",";
                //商品使用优惠券信息  拿商品id做key
                $goods_use_coupon_info[$value['goods_id']] = array(
                    'goods_id'       => $value['goods_id'],
                    'coupon_code'    => $value['use_coupon_code'],
                    'discount_point' => $discount_point,
                    'discount_price' => $discount_money,
                );
            }
        }
        $discount['goods_use_coupon_info'] = $goods_use_coupon_info;
        $discount['use_coupon_count']      = count($canUseCoupon);
        $discount['use_coupon_code']       = $use_coupon_code;
        $data                              = array_merge($buyGoodsList, $discount);

        return $data;
    }

    /**
     *
     * 获取优惠券当成商品售卖的 订单详情里的 优惠券
     *
     * @param $couponGroupIds
     * @param $user_id
     * @param $receive_order_no
     *
     * @return array
     */
    public function getOrderDetailCoupon($couponGroupIds, $user_id, $receive_order_no)
    {
        if (empty($couponGroupIds) || empty($user_id)) {
            return array();
        }

        $couponGroupIdStr = join("','", $couponGroupIds);
        //获取下优惠状态已经是否过期正常
        $couponDb         = new IQuery('coupon_user as cu');
        $couponDb->join   = "left join coupon as c  on c.id = cu.coupon_id";
        $couponDb->where  = "cu.coupon_group_id in($couponGroupIdStr) and cu.user_id=$user_id and receive_order_no=$receive_order_no";
        $couponDb->fields = "cu.*,c.*";
        $couponQuery      = $couponDb->find();
        if (empty($couponQuery)) {
            return array();
        }
        $couponData = array();
        foreach ($couponQuery as $key => $value) {
            $couponData[$value['coupon_group_id']][] = $value;
        }

        return $couponData;
    }

    /**
     * 更新订单里相关联的优惠卷
     *
     * @param $couponGroupIds
     * @param $user_id
     * @param $receive_order_no
     * @param $set_status
     * @param $where_status
     *
     * @return bool
     */
    public function updateOrderDetailCoupon($couponGroupIds, $user_id, $receive_order_no, $set_status, $where_status)
    {
        if (empty($couponGroupIds) || empty($user_id) || empty($set_status) || empty($where_status)) {
            return false;
        }

        $db                  = IDBFactory::getDB();
        $couponTableName     = IWeb::$app->config['DB']['tablePre'] . "coupon";
        $couponUserTableName = IWeb::$app->config['DB']['tablePre'] . "coupon_user";
        $sql                 = "UPDATE {$couponTableName} as c  LEFT JOIN  {$couponUserTableName} as cu ON cu.coupon_id= c.id 
                                set  c.status = {$set_status} 
                                where  cu.coupon_group_id={$couponGroupIds} and cu.user_id={$user_id} and c.status={$where_status} and cu.receive_order_no={$receive_order_no}";
        $upRes               = $db->query($sql);

        return $upRes;
    }

}